﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using CodeCounsel.SharePoint.RibbonDesigner.Model;
using CodeCounsel.SharePoint.RibbonDesigner.View.AttachedBehaviors;

namespace CodeCounsel.SharePoint.RibbonDesigner.ViewModel
{
    public class TabViewModel
        : DomainViewModel<Tab>, IDropProcessor, IDragProcessor
    {
        int _scaleIndex;
        RibbonTemplates _templates;
        ObservableCollection<GroupViewModel> _groupViewModels;
        bool _showScalePicker = true;

        public IEnumerable<GroupViewModel> Groups 
        { 
            get 
            {
                if (_groupViewModels.Count != Model.Children.Count)
                {
                    CreateGroupViewModel();
                }
                return _groupViewModels; 
            } 
        }

        public ScalePickerViewModel ScalePicker { get; private set; }

        public bool ShowScalePicker
        {
            get { return _showScalePicker; }
            set
            {
                if (value != _showScalePicker)
                {
                    _showScalePicker = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("ShowScalePicker"));
                }
            }
        }

        public int ScaleCount
        {
            get { return Model.Scaling.Scales.Count(); }
        }

        public int ScaleIndex
        {
            get { return _scaleIndex; }
        }

        public virtual string Title
        {
            get { return Model.Title; }
        }

        public string Id
        {
            get { return Model.Id.ToString(); }
        }

        public TabViewModel(Tab tab, RibbonTemplates templates)
            : base(tab)
        {
            ScalePicker = new ScalePickerViewModel(this);
            _templates = templates; 
            _scaleIndex = -1;
            _groupViewModels = new ObservableCollection<GroupViewModel>();
        }

        public void ScaleDown()
        {
            List<Scale> scales = Model.Scaling
                .OfType<Scale>()
                .ToList();
            _scaleIndex++;
            GroupSize nextScale = scales[_scaleIndex];
            Group group = Model.Items.Where(g => g.Id == nextScale.GroupId).FirstOrDefault();
            if (group != null)
            {
                GroupViewModel viewModel = Groups.Where(v => v.Id == group.Id).First();

                IEnumerable<GroupTemplate> groupTemplates = ExtensionManager.GetReplacedChildren<GroupTemplate>(_templates);
                Layout layout = GetLayout(group, nextScale, groupTemplates);
                bool isPopup = layout.IsPopup;
                if(isPopup)
                {
                    layout = GetLayout(group, layout.LayoutTitle, groupTemplates);
                }
                viewModel.SetLayout(layout, isPopup);
            }
        }

        public void ScaleUp()
        {
            List<Scale> scales = Model.Scaling
                .OfType<Scale>()
                .ToList();
            Scale nextScale = scales[_scaleIndex];
            Group group = Model.Items.Where(g => g.Id == nextScale.GroupId).FirstOrDefault();
            if (group != null)
            {
                GroupSize scale = scales.Where(s => s.GroupId == nextScale.GroupId)
                    .Where(s => s.Sequence <= nextScale.Sequence)
                    .Where(s => s != nextScale)
                    .OrderBy(s => s.Sequence).LastOrDefault();
                if (scale == null)
                {
                    scale = Model.Scaling.OfType<MaxSize>()
                        .Where(d => d.GroupId == group.Id)
                        .First();
                }
                IEnumerable<GroupTemplate> groupTemplates = ExtensionManager.GetReplacedChildren<GroupTemplate>(_templates);
                 GroupViewModel viewModel = Groups.Where(v => v.Id == group.Id).First();
                Layout layout = GetLayout(group, scale, groupTemplates);
                bool isPopup = layout.IsPopup;
                if (isPopup)
                {
                    layout = GetLayout(group, layout.LayoutTitle, groupTemplates);
                }
                viewModel.SetLayout(layout, isPopup);
            }
            _scaleIndex--;
        }

        void CreateGroupViewModel()
        {
            _groupViewModels.Clear();
            GroupContainer groupContainer = ExtensionManager.GetReplacedChild<GroupContainer>(
                Model, Model.Items);
            Scaling scaling = ExtensionManager.GetReplacedChild<Scaling>(
                Model, Model.Scaling);
            if (groupContainer != null && scaling != null)
            {
                IEnumerable<GroupTemplate> groupTemplates = ExtensionManager.GetReplacedChildren<GroupTemplate>(_templates);
                foreach (Group group in ExtensionManager.GetReplacedChildren<Group>(
                    groupContainer))
                {
                    MaxSize maxSize = ExtensionManager.GetReplacedChildren<MaxSize>(scaling)
                            .Where(d => d.GroupId == group.Id)
                            .FirstOrDefault();
                    if (maxSize != null)
                    {
                        Layout layout = GetLayout(group, maxSize, groupTemplates);
                        _groupViewModels.Add(new GroupViewModel(group, layout));
                    }
                }
            }
        }

        Layout GetLayout(Group group, GroupSize sizeInfo, IEnumerable<GroupTemplate> groupTemplates)
        {
            return GetLayout(group, sizeInfo.Size, groupTemplates);
        }

        Layout GetLayout(Group group, string layoutName, IEnumerable<GroupTemplate> groupTemplates)
        {
            GroupTemplate template = groupTemplates
                .Where(gt => gt.Id != null && gt.Id == group.Template)
                .First();
            Layout layout = template.Layouts
                .Where(l => l.Title == layoutName)
                .First();

            return layout;
        }

        bool IDropProcessor.CanDrop(object draggedData)
        {
            return draggedData is GroupViewModel;
        }

        void IDropProcessor.PerformDrop(object value, int insertionIndex)
        {
            GroupViewModel viewModel = (GroupViewModel)value;
            _groupViewModels.Insert(insertionIndex, viewModel);
        }

        bool IDragProcessor.CanDrag(object draggedData)
        {
            return draggedData is GroupViewModel;
        }

        int IDragProcessor.RemoveItem(object draggedData)
        {
            GroupViewModel viewModel = (GroupViewModel)draggedData;
            int index = _groupViewModels.IndexOf(viewModel);
            _groupViewModels.Remove(viewModel);
            return index;
        }
    }
}
